#ifndef _IRQ_H
#define _IRQ_H

#include <types.h>
#include <arch/irq.h>
#include <util.h>

enum irqreturn {
    IRQ_NONE        = 0,
    IRQ_HANDLED     = 1,
};

typedef enum irqreturn irqreturn_t;

#define IRQF_MASKED				(1 << 0)
#define IRQF_INPROGRESS			(1 << 1)
#define IRQF_PENDING			(1 << 2)
#define IRQF_NOREQUEST			(1 << 3)
#define IRQF_VALID				(0)
#define IRQF_SET_TYPE_MASKED	(1 << 4)
#define IRQF_MASK				(0x1f)

#define irqf_is_masked(flags)			((flags) & IRQF_MASKED)
#define irqf_is_unmasked(flags)			(((flags) & IRQF_MASKED) == 0)
#define irqf_is_inprogress(flags)		((flags) & IRQF_INPROGRESS)
#define irqf_is_pending(flags)			((flags) & IRQF_PENDING)
#define irqf_is_norequest(flags)		((flags) & IRQF_NOREQUEST)
#define irqf_is_valid(flags)			(((flags) & IRQF_NOREQUEST) == 0)
#define irqf_is_set_type_masked(flags)	((flags) & IRQF_SET_TYPE_MASKED)

#define irqf_set_masked(flags)			((flags) |= IRQF_MASKED)
#define irqf_set_unmasked(flags)		((flags) &= ~IRQF_MASKED)
#define irqf_set_inprogress(flags)		((flags) |= IRQF_INPROGRESS)
#define irqf_set_pending(flags)			((flags) |= IRQF_PENDING)
#define irqf_set_norequest(flags)		((flags) |= IRQF_NOREQUEST)
#define irqf_set_valid(flags)			((flags) &= ~IRQF_NOREQUEST)
#define irqf_set_set_type_masked(flags)	((flags) |= IRQF_SET_TYPE_MASKED)

#define irqf_clr_inprogress(flags)		((flags) &= ~IRQF_INPROGRESS)
#define irqf_clr_pending(flags)			((flags) &= ~IRQF_PENDING)
#define irqf_clr_set_type_masked(flags)	((flags) &= ~IRQF_SET_TYPE_MASKED)

#define IRQT_EDGE_RISING    (1 << 0)
#define IRQT_EDGE_FALLING	(1 << 1) 
#define IRQT_EDGE_BOTH		(IRQT_EDGE_RISING | IRQT_EDGE_FALLING)
#define IRQT_LEVEL_HIGH		(1 << 2)
#define IRQT_LEVEL_LOW		(1 << 3)
#define IRQT_MASK			(0xf)

struct irq_desc;

typedef void (*irq_flow_handler_t)(struct irq_desc *desc);

struct irq_chip {
    void (*irq_ack)(struct irq_desc *desc);
    void (*irq_mask)(struct irq_desc *desc);
    void (*irq_mask_ack)(struct irq_desc *desc);
    void (*irq_unmask)(struct irq_desc *desc);
	int  (*irq_set_type)(struct irq_desc *desc, unsigned int type);
	void (*irq_enable)(struct irq_desc *desc);
	void (*irq_disable)(struct irq_desc *desc);
};

typedef irqreturn_t (*irq_handler_t)(unsigned int irq, void *priv);

#define IRQAF_DISABLED			(0x1)
#define IRQAF_SAMPLE_RANDOM		(0x2)
#define IRQAF_MASK				(0x3)

#define irqaf_is_disabled(flags)		((flags) & IRQAF_DISABLED)
#define irqaf_is_enabled(flags)			(((flags) & IRQAF_DISABLED) == 0)
#define irqaf_is_sample_random(flags)	((flags) & IRQAF_SAMPLE_RANDOM)

#define irqaf_set_disabled(flags)		((flags) |= IRQAF_DISABLED)
#define irqaf_set_enabled(flags)		((flags) &= ~IRQAF_DISABLED)
#define irqaf_set_sample_random(flags)	((flags) |= IRQAF_SAMPLE_RANDOM)

#define irqaf_clr_sample_random(flags)	((flags) &= ~IRQAF_SAMPLE_RANDOM)

struct irqaction {
	unsigned int flags;
	irq_handler_t handler;
	void *priv;
	struct irqaction *next;
};

struct irq_desc {
	unsigned int		irq;
	unsigned int		flags;
	struct irq_chip		*chip;
	irq_flow_handler_t  handle_irq;
	struct irqaction	*action; 
	int usage;
};

#define local_irq_enable()			do { arch_local_irq_enable(); } while (0)
#define local_irq_disable()			do { arch_local_irq_disable(); } while (0)
#define local_irq_save(flags)		do { flags = arch_local_irq_save(); } while (0)
#define local_irq_restore(flags)	do { arch_local_irq_restore(flags); } while (0)

int irq_set_chip(unsigned int irq, struct irq_chip *chip);
int irq_set_handler(unsigned int irq, irq_flow_handler_t handle);  
int irq_set_flags(unsigned int irq, unsigned int flags);   
int irq_set_type(unsigned int irq, unsigned int type);     
void do_irq(unsigned int irq);    
int generic_handle_irq(unsigned int irq);         
void handle_level_irq(struct irq_desc *desc);
void handle_edge_irq(struct irq_desc *desc);   
int request_irq(unsigned int irq, struct irqaction *action, irq_handler_t handler, unsigned int flags, void *priv);
void disable_irq(unsigned int irq);
void enable_irq(unsigned int irq);
void free_irq(unsigned int irq, void *priv);

#endif /* _IRQ_H */

